/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkSocket/MkSocket.h"
#include "MkEvent/MkEvent.h"
//#include "MkNetworkUtil.h"
#include "MkUtil/MkUtil.h"
#include "MkUtil/MkLog.h"
#ifndef _WIN32
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include<sys/socket.h>
#include<unistd.h>
#include <fcntl.h>
#endif

#define MaxSendCount   10
Uint64 CMkSocket::m_SessionIndex = 0;
Uint64 CMkSocket::m_TcpActiveMs = 30 * 1000;
Uint32 CMkSocket::m_TcpSendFailCumulativeMs = 3 * 1000;   //3 sec
Uint32 CMkSocket::m_TcpSendFailCumulativeMB = 20;         //20MB
Uint32 CMkSocket::m_UdpSendFailCumulativeMs = 3 * 1000;   //3 sec
Uint32 CMkSocket::m_UdpSendFailCumulativeMB = 20;         //20MB
CMkSocket::CMkSocket(const MkSocketType& SocketType, CMkEvent* pEvent, CMkTimer* pTimer)
    : m_SockType(SocketType)
    , m_Socket(INVALID_SOCKET)
    , m_LocalPort(0)
    , m_RemotePort(0)
    , m_pEvent(pEvent)
    , m_pTimer(pTimer)
    , m_bConntected(SocketType >= TcpSession)  //set connected when tcp session or udp session
    , m_TotalRecvLen(0)
    , m_TotalSendLen(0)
    , m_SessionId(m_SessionIndex++)
    , m_ActiveTime(NowMkTime)
{

}

Uint32 CMkSocket::GetUnSendBufferLength() const
{
    return m_UnSendList.GetTatolLen();
}

Uint32 CMkSocket::SetSocket(SOCKET sock, Uint32 Event)
{
    if (!m_pEvent) {
        return UnInited;
    }
    m_Socket = sock;
    SetNoSigpipe();
    SetNoBlocked();
    SetSendBufferLen();
    SetRecvBufferLen();
    SetCloseWait();
    SetNoDelay();
    SetReuseable();
    SetKeepAlive();
    if (TcpSession == m_SockType) {
        GetPeerAddr();
    }
    return m_pEvent->AddEventer(m_Socket, Event, [this](Uint32 Event) {
        OnEvent(Event);
    });
}

Uint32 CMkSocket::Create(BOOL bReuse/*=TRUE*/)
{
    if (INVALID_SOCKET != m_Socket) {
        closesocket(m_Socket);
        shutdown(m_Socket, 1);
        m_Socket = INVALID_SOCKET;
    }
#ifdef _WIN32
    m_Socket = WSASocket(AF_INET, UdpSession == m_SockType ? SOCK_DGRAM : SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
#else
    m_Socket = socket(AF_INET, UdpSession == m_SockType ? SOCK_DGRAM : SOCK_STREAM, 0);
#endif
    if (INVALID_SOCKET == m_Socket) {
        return SocketCreateFailed;
    }
    SetNoSigpipe();
    SetNoBlocked();
    SetSendBufferLen();
    SetRecvBufferLen();
    if (UdpSession != m_SockType) {
        SetCloseWait();
        SetNoDelay();
        SetKeepAlive();
    }
    if (bReuse) {
        SetReuseable();
    }
    return NoneError;
}

Uint32 CMkSocket::Close()
{
    SOCKET CurSock = m_Socket;
    if (INVALID_SOCKET != m_Socket) {
        closesocket(m_Socket);
        shutdown(m_Socket, 1);
        m_Socket = INVALID_SOCKET;

    }
    if (nullptr != m_pEvent) {
        m_pEvent->DeleteEventer(CurSock);
    }
    m_bConntected = FALSE;
    return NoneError;
}

Uint32 CMkSocket::Connect(const MkString& Ip, Uint16 Port)
{
    if (!m_pEvent) {
        return UnInited;
    }
    m_RemoteHost = Ip;
    m_RemotePort = Port;
    SetConnectTimeOut(3);
    struct sockaddr_in RemoteAddr;
    RemoteAddr.sin_family = AF_INET;
    RemoteAddr.sin_port = htons(Port);
    RemoteAddr.sin_addr.s_addr = inet_addr(Ip.c_str());
    socklen_t addrlen = sizeof(struct sockaddr);
    int nRet = connect(m_Socket, (struct sockaddr *)&RemoteAddr, addrlen);
    Uint32 ErrorCode = m_pEvent->AddEventer(m_Socket, CMkEvent::EventRead | CMkEvent::EventWrite | CMkEvent::EventError, [this](Uint32 Event) {
        OnEvent(Event);
    });
    if (0 == nRet) {
        OnConnect();
    }
    return ErrorCode;
}

Uint32 CMkSocket::Bind(Uint16 Port, const MkString& Ip/* = ""*/)
{
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(Port);
    local.sin_addr.s_addr = Ip.empty() ? 0 : inet_addr(Ip.c_str());
    socklen_t addrlen = sizeof(struct sockaddr);

    int nRet = bind(m_Socket, (struct sockaddr *)&local, addrlen);
    if (-1 == nRet) {
        MkErrorLog("bind socket failed\n");
        closesocket(m_Socket);
        return SocketBindFailed;
    }
    GetLocalAddr();
    return m_pEvent->AddEventer(m_Socket, CMkEvent::EventRead, [this](Uint32 Event) {
        OnEvent(Event);
    });
}

Uint32 CMkSocket::Listen(int BackLog/* = DefauleBackLog*/)
{
    int nRet = listen(m_Socket, BackLog);
    if (0 != nRet) {
        MkErrorLog("listen socket:%d failed:%d\n", m_Socket, errno);
        return SocketListenFailed;
    }
    if (!m_pEvent) {
        return UnInited;
    }
    return NoneError;
}

Uint32 CMkSocket::SetNoDelay(BOOL bOn/* = TRUE*/)
{
    int Opt = bOn ? 1 : 0;
    int nRet = setsockopt(m_Socket, IPPROTO_TCP, TCP_NODELAY, (char *)&Opt, static_cast<socklen_t>(sizeof(Opt)));
    if (-1 == nRet) {
        MkErrorLog("set socket no delay failed bOn:%d\n", bOn);
        return SocketSetOptFailed;
    }
    return NoneError;
}

Uint32 CMkSocket::SetNoSigpipe(BOOL bOn/* = TRUE*/)
{
#if defined(SO_NOSIGPIPE)
    int set = bOn;
    auto ret = setsockopt(m_Socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&set, sizeof(int));
    if (ret == -1) {
        MkErrorLog("set socket no sigpipe");
        return SocketSetOptFailed;
    }
#endif
    return NoneError;
}

Uint32 CMkSocket::SetNoBlocked(BOOL bOn/* = TRUE*/)
{
#ifdef _WIN32
    unsigned long ul = bOn;
#else
    int ul = bOn;
#endif //defined(_WIN32)
    int nRet = ioctlsocket(m_Socket, FIONBIO, &ul);
    if (-1 == nRet) {
        MkErrorLog("set socket no block failed bOn:%d", bOn);
        return SocketIoctlFailed;
    }
    return NoneError;
}

Uint32 CMkSocket::SetRecvBufferLen(int nSize/* = Len1M*/)
{
    int nRet = setsockopt(m_Socket, SOL_SOCKET, SO_RCVBUF, (char *)&nSize, sizeof(nSize));
    if (-1 == nRet) {
        MkErrorLog("set recv buffer len:%d failed\n", nSize);
        return SocketSetOptFailed;
    }
    return NoneError;
}

Uint32 CMkSocket::SetSendBufferLen(int nSize/* = Len1M*/)
{
    int nRet = setsockopt(m_Socket, SOL_SOCKET, SO_SNDBUF, (char *)&nSize, sizeof(nSize));
    if (-1 == nRet) {
        MkErrorLog("set send buffer len:%d failed\n", nSize);
        return SocketSetOptFailed;
    }
    return NoneError;
}

Uint32 CMkSocket::SetReuseable(BOOL bOn/* = TRUE*/)
{
    int Opt = bOn ? 1 : 0;
    int nRet = setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, (char *)&Opt, static_cast<socklen_t>(sizeof(Opt)));
    if (-1 == nRet) {
        MkErrorLog("socket set reuse address failed\n");
        return SocketSetOptFailed;
    }
    return NoneError;
}

Uint32 CMkSocket::SetKeepAlive(BOOL bOn/* = TRUE*/)
{
    int Opt = bOn ? 1 : 0;
    int nRet = setsockopt(m_Socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&Opt, static_cast<socklen_t>(sizeof(Opt)));
    if (-1 == nRet) {
        MkErrorLog("set socket keepalive failed on:%d\n", bOn);
        return SocketSetOptFailed;
    }
    return NoneError;
}

Uint32 CMkSocket::SetCloseWait(Uint32 Second/* = DefaultCloseWait*/)
{
    linger m_sLinger;
    m_sLinger.l_onoff = (Second > 0);
    m_sLinger.l_linger = Second;
    int nRet = setsockopt(m_Socket, SOL_SOCKET, SO_LINGER, (char *)&m_sLinger, sizeof(linger));
    if (-1 == nRet) {
        MkErrorLog("set close wait time:%d failed\n", Second);
        return SocketSetOptFailed;
    }
    return NoneError;
}

Uint32 CMkSocket::SetCloExec(BOOL bOn/* = TRUE*/)
{
#ifdef _WIN32
    return NoneError;
#else
    int flags = fcntl(m_Socket, F_GETFD);
    if (flags == -1) {
        return SystemError;
    }
    if (bOn) {
        flags |= FD_CLOEXEC;
    } else {
        int cloexec = FD_CLOEXEC;
        flags &= ~cloexec;
    }
    int ret = fcntl(m_Socket, F_SETFD, flags);
    if (ret == -1) {
        return SystemError;
    }
    return NoneError;
#endif
}

Uint32 CMkSocket::SetConnectTimeOut(Uint32 nSeconds)
{
#ifndef _WIN32
    Uint32 Syncnt = 0;
    while (0 == (nSeconds >> 1)) {
        Syncnt++;
    }
    if (Syncnt > 1) {
        Syncnt--;
    }
    setsockopt(m_Socket, IPPROTO_TCP, TCP_SYNCNT, &Syncnt, sizeof(Syncnt));
#endif
    return NoneError;
}

Uint32 CMkSocket::Accept(CMkSocket* pAccectSock)
{
    struct sockaddr_in Remote;
    socklen_t addrlen = sizeof(struct sockaddr);
#ifdef _WIN32
    SOCKET fd = WSAAccept(m_Socket, (sockaddr*)&Remote, &addrlen, NULL, NULL);
#else
    SOCKET fd = accept(m_Socket, (sockaddr*)&Remote, &addrlen);
#endif
    if (INVALID_SOCKET == fd) {
        MkErrorLog("accept failed\n");
        return SocketAcceptFailed;
    }

    pAccectSock->SetSocket(fd, CMkEvent::EventError | CMkEvent::EventRead);
    return NoneError;
}

Uint32 CMkSocket::Send(const Uint8* pBuf, Uint32 nLen)
{
    CMkBufferList BufferList;
    Uint32 nOffset = 0;
    while (nOffset < nLen) {
        if (nOffset + MtuSize > nLen) {
            BufferList.Append(pBuf + nOffset, nLen - nOffset);
            nOffset = nLen;
        } else {
            BufferList.Append(pBuf + nOffset, MtuSize);
            nOffset += MtuSize;
        }
    }
    return Send(BufferList);
}

Uint32 CMkSocket::Send(const CMkBufferList& BufList)
{
    // socket has closed
    Uint32 ErrorCode = NoneError;
    Uint32 NotSendCount = 0;
    CMkTime BeginUnSendTime;
    m_UnSendLock.Lock();
    if (!m_UnSendList.Empty() || !m_bConntected) {
        m_UnSendList.Append(BufList);
        if (m_pEvent) {
            m_pEvent->ModifyEventer(m_Socket, CMkEvent::EventRead | CMkEvent::EventWrite | CMkEvent::EventError);
        }
        ErrorCode = SocketSendCached;
        m_UnSendList.GetBeginBuildTime(BeginUnSendTime);
        NotSendCount = m_UnSendList.GetTatolLen();
    }
    m_UnSendLock.Unlock();

    if ((!BeginUnSendTime.IsEmpty() && NowMkTime > BeginUnSendTime + (Uint64)m_TcpSendFailCumulativeMs * 1000)
        || NotSendCount > m_TcpSendFailCumulativeMB*Len1M) {
        MkErrorLog("this:%p has 10 seconds before buffer is not send success or not send count:%d is big than 200M  has close\n", this, NotSendCount);
        Close();
        return SocketClosed;
    }
    if (NoneError != ErrorCode) {
        return ErrorCode;
    }

    m_ActiveTime = NowMkTime;
    MkListBuffer::const_iterator it = BufList.GetBufferList().begin();
    Uint32 nSendLen = 0;
#ifdef _WIN32
    WSABUF  *pBufs = (WSABUF*)malloc(sizeof(WSABUF)*BufList.GetBufferList().size());
    for (Uint32 i = 0; it != BufList.GetBufferList().end(); it++, i++) {
        pBufs[i].buf = (Int8*)it->GetBuffer();
        pBufs[i].len = it->GetLength();
    }
    DWORD ByteToSend = 0;
    if (WSASend(m_Socket, pBufs, BufList.GetBufferList().size(), &ByteToSend, 0, NULL, NULL)) {
        //send failed
        ByteToSend = 0;
    }
    free(pBufs);
    nSendLen = ByteToSend;
#else
    struct iovec *pBufs = (struct iovec *)malloc(sizeof(struct iovec)*BufList.GetBufferList().size());
    Uint32 i = 0;
    for (; it != BufList.GetBufferList().end(); it++, i++) {
        pBufs[i].iov_base = (Int8*)it->GetBuffer();
        pBufs[i].iov_len = it->GetLength();
    }
    nSendLen = writev(m_Socket, pBufs, i);
    if (-1 == nSendLen) {
        nSendLen = 0;
    }
    free(pBufs);
#endif
    m_TotalSendLen += nSendLen;
    if (nSendLen != BufList.GetTatolLen()) {
        m_UnSendLock.Lock();
        it = BufList.GetBufferList().begin();
        for (; it != BufList.GetBufferList().end(); it++) {
            if (nSendLen > it->GetLength()) {
                nSendLen -= it->GetLength();
                continue;
            } else {
                m_UnSendList.Append((void*)((Uint8*)it->GetBuffer() + nSendLen), it->GetLength() - nSendLen);
                nSendLen = 0;
            }
        }
        m_UnSendLock.Unlock();
        if (m_pEvent) {
            m_pEvent->ModifyEventer(m_Socket, CMkEvent::EventRead | CMkEvent::EventWrite | CMkEvent::EventError);
        }
        ErrorCode = UnknownError;
    }
    return ErrorCode;
}

Uint32 CMkSocket::Recv(Uint8* pBuf, INOUT Uint32& nLen)
{
    Uint32 nCount = (nLen / MtuSize) + ((nLen%MtuSize) ? 1 : 0);
#ifdef _WIN32
    WSABUF  *pBufs = (WSABUF *)malloc(sizeof(WSABUF)*nCount);
    for (Uint32 i = 0; i < nCount; i++) {
        pBufs[i].buf = (Int8*)pBuf + i * MtuSize;
        pBufs[i].len = (i == nCount - 1) ? ((nLen%MtuSize)) : MtuSize;
        pBufs[i].len = 0 == pBufs[i].len ? MtuSize : pBufs[i].len;
        DWORD Flags = 0;
    }
    DWORD BytesRecv;
    DWORD Flags = 0;
    if (WSARecv(m_Socket, pBufs, nCount, &BytesRecv, &Flags, NULL, NULL)) {
        free(pBufs);
        nLen = 0;
        MkErrorLog("recv error:%p\n", this);
        Close();
        return SocketRecvFailed;
    }
    free(pBufs);
    nLen = BytesRecv;
#else
    struct iovec *pBufs = (struct iovec*)malloc(sizeof(struct iovec)*nCount);
    Uint32 i = 0;
    for (; i < nCount; i++) {
        pBufs[i].iov_base = (Int8*)pBuf + i * MtuSize;
        pBufs[i].iov_len = (i == nCount - 1) ? (nLen%MtuSize) : MtuSize;
        pBufs[i].iov_len = 0 == pBufs[i].iov_len ? MtuSize : pBufs[i].iov_len;
    }
    nLen = readv(m_Socket, pBufs, i);
    if (-1 == nLen) {
        MkDebugLog("recv error:%p\n", this);
        nLen = 0;
        free(pBufs);
        Close();
        return SocketRecvFailed;
    }
    free(pBufs);
#endif
    m_ActiveTime = NowMkTime;
    m_TotalRecvLen += nLen;
    return NoneError;
}

Uint32 CMkSocket::SendTo(const MkString& Ip, Uint16 Port, const Uint8* pBuf, Uint32 nLen)
{
    struct sockaddr_in RemoteAddr;
    RemoteAddr.sin_family = AF_INET;
    RemoteAddr.sin_port = htons(Port);
    RemoteAddr.sin_addr.s_addr = inet_addr(Ip.c_str());
    return SendTo(RemoteAddr, pBuf, nLen);
}

Uint32 CMkSocket::SendTo(const MkString& Ip, Uint16 Port, const CMkBufferList& BufferList)
{
    struct sockaddr_in RemoteAddr;
    RemoteAddr.sin_family = AF_INET;
    RemoteAddr.sin_port = htons(Port);
    RemoteAddr.sin_addr.s_addr = inet_addr(Ip.c_str());
    return SendTo(RemoteAddr, BufferList);
}

Uint32 CMkSocket::SendTo(const struct sockaddr_in& Dest, const Uint8* pBuf, Uint32 nLen)
{
    CMkBufferList BufferList;
    BufferList.Append(pBuf, nLen);
    return SendTo(Dest, BufferList);
}

Uint32 CMkSocket::SendTo(const struct sockaddr_in& Dest, const CMkBufferList& BufferList)
{
    Uint32 ErrorCode = NoneError;
    CMkTime BeginUnSendTime;
    Uint32 NotSendCount = 0;
    m_UnSendLock.Lock();
    if (!m_UdpUnSendList.empty()) {
        CMkStorageBufferList StorageList;
        StorageList.Append(BufferList);
        m_UdpUnSendList.emplace_back(StorageList);
        m_UdpUnSendList.begin()->GetBeginBuildTime(BeginUnSendTime);
        MkVector<CMkStorageBufferList>::iterator it = m_UdpUnSendList.begin();
        for (; it != m_UdpUnSendList.end(); it++) {
            NotSendCount += it->GetTatolLen();
        }
        if ((!BeginUnSendTime.IsEmpty() && NowMkTime > BeginUnSendTime + (Uint64)m_UdpSendFailCumulativeMs * 1000)
            || NotSendCount > m_UdpSendFailCumulativeMB*Len1M) {
            MkErrorLog("this:%p has %d seconds before buffer is not send success or not send count:%d is big than %d MB  has close\n", this, m_UdpSendFailCumulativeMs / 1000, NotSendCount, m_UdpSendFailCumulativeMB);
            m_UdpUnSendList.clear();
        }
    }
    m_UnSendLock.Unlock();
    if (BeginUnSendTime.IsEmpty()) {
        //not has unsend
        Uint32 nCount = BufferList.GetBufferList().size();
#ifdef _WIN32
        WSABUF  *pBufs = (WSABUF *)malloc(sizeof(WSABUF)*nCount);
        MkListBuffer::const_iterator it = BufferList.GetBufferList().begin();
        for (Uint32 i = 0; i < nCount&&it != BufferList.GetBufferList().end(); it++, i++) {
            pBufs[i].buf = (Int8*)it->GetBuffer();
            pBufs[i].len = it->GetLength();
        }
        socklen_t AddrLen = sizeof(struct sockaddr);
        DWORD ByteToSend = 0;
        if (WSASendTo(m_Socket, pBufs, nCount, &ByteToSend, 0, (sockaddr*)&Dest, AddrLen, nullptr, nullptr)) {
            ErrorCode = SocketSendFailed;
        }
        free(pBufs);
        m_TotalSendLen += ByteToSend;
#else
        struct msghdr hdr;
        hdr.msg_name = (void*)&Dest;
        hdr.msg_namelen = sizeof(struct sockaddr_in);
        struct iovec *pBufs = (struct iovec*)malloc(sizeof(struct iovec)*nCount);
        MkListBuffer::const_iterator it = BufferList.GetBufferList().begin();
        for (Uint32 i = 0; i < nCount&&it != BufferList.GetBufferList().end(); it++, i++) {
            pBufs[i].iov_base = (Int8*)it->GetBuffer();
            pBufs[i].iov_len = it->GetLength();
        }
        hdr.msg_iov = pBufs;
        hdr.msg_iovlen = nCount;
        hdr.msg_control = 0;
        hdr.msg_controllen = 0;
        hdr.msg_flags = 0;
        sendmsg(m_Socket, &hdr, 0);
        MkFree(pBufs);
        m_TotalSendLen += BufferList.GetTatolLen();
#endif
        if (NoneError != ErrorCode) {
            m_UnSendLock.Lock();
            CMkStorageBufferList StorageList;
            StorageList.Append(BufferList);
            m_UdpUnSendList.emplace_back(StorageList);
            m_UnSendLock.Unlock();
            ErrorCode = SocketSendCached;
        } else {
            m_ActiveTime = NowMkTime;
        }
    }
    return ErrorCode;
}

Uint32 CMkSocket::RecvFrom(Uint8* pBuf, INOUT Uint32& nLen, OUT MkString& Ip, OUT Uint16& Port)
{
    struct sockaddr_in RemoteAddr;
    socklen_t addrlen = sizeof(struct sockaddr);
    int nRead = recvfrom(m_Socket, (Int8*)pBuf, nLen, 0, (sockaddr*)&RemoteAddr, &addrlen);
    if (-1 == nRead) {
        return SocketRecvFailed;
    }
    Ip = inet_ntoa(RemoteAddr.sin_addr);
    Port = htons(RemoteAddr.sin_port);
    nLen = nRead;
    m_ActiveTime = NowMkTime;
    m_TotalRecvLen += nLen;
    return NoneError;
}

Uint32 CMkSocket::OnRecv()
{
    return NoneError;
}

Uint32 CMkSocket::OnRecvFrom()
{
    return NoneError;
}

Uint32 CMkSocket::OnAccept()
{
    return NoneError;
}

Uint32 CMkSocket::OnConnect()
{
    m_bConntected = TRUE;
    GetLocalAddr();
    return NoneError;
}

Uint32 CMkSocket::OnClose()
{
    m_bConntected = FALSE;
    return Close();
}

Uint32 CMkSocket::OnWrite()
{
    m_bWriteAble = TRUE;
    if (!m_bConntected) {
        OnConnect();
    }

    if (0 == m_UnSendList.GetBufferCount()
        && m_pEvent) {
        m_pEvent->ModifyEventer(m_Socket, CMkEvent::EventRead | CMkEvent::EventError);
        return NoneError;
    }

    Uint32 nToSendLen = 0;
    Uint32 nSendLen = 0;
    m_UnSendLock.Lock();
    MkListStorageBuffer::const_iterator it = m_UnSendList.GetStorageBufferList().begin();
    Uint32 nSendCount = m_UnSendList.GetStorageBufferList().size();
#ifdef _WIN32
    WSABUF  *pBufs = (WSABUF*)malloc(sizeof(WSABUF)*nSendCount);
    for (int i = 0; it != m_UnSendList.GetStorageBufferList().end(); it++, i++) {
        nToSendLen += (*it)->GetLength();
        pBufs[i].buf = (Int8*)(*it)->GetBuffer();
        pBufs[i].len = (*it)->GetLength();
    }
    DWORD ByteToSend = 0;
    if (WSASend(m_Socket, pBufs, nSendCount, &ByteToSend, 0, NULL, NULL)) {
        //send failed
        ByteToSend = 0;
    }
    nSendLen = ByteToSend;
#else
    struct iovec *pBufs = (struct iovec*)malloc(sizeof(struct iovec)*nSendCount);
    Uint32 i = 0;
    for (; it != m_UnSendList.GetStorageBufferList().end(); it++, i++) {
        nToSendLen += (*it)->GetLength();
        pBufs[i].iov_base = (Int8*)(*it)->GetBuffer();
        pBufs[i].iov_len = (*it)->GetLength();
    }
    nSendLen = writev(m_Socket, pBufs, i);
    if (-1 == nSendLen) {
        nSendLen = 0;
    }
#endif
    free(pBufs);
    m_TotalSendLen += nSendLen;
    m_ActiveTime = NowMkTime;
    CMkTime FirstBuildTime;
    m_UnSendList.RemoveBegin(nSendLen);
    m_UnSendList.GetBeginBuildTime(FirstBuildTime);
    m_UnSendLock.Unlock();
    if (nSendLen != nToSendLen && m_pEvent) {
        m_pEvent->ModifyEventer(m_Socket, CMkEvent::EventRead | CMkEvent::EventWrite | CMkEvent::EventError);
    }
    //has 10 second buffer before not send success
    if (m_UnSendList.GetTatolLen() > 0) {
        if (NowMkTime - FirstBuildTime > 1000 * 1000 * 10
            || m_UnSendList.GetTatolLen() > Len1M * 10) {
            MkWarningLog("socket has 10 seconds buffer send failed close it\n");
            Close();
            return SocketClosed;
        }
    } else {
        if (m_pEvent) {
            m_pEvent->ModifyEventer(m_Socket, CMkEvent::EventRead | CMkEvent::EventError);
        }
    }
    return NoneError;
    }

Uint32 CMkSocket::OnEventRemoved()
{
    return NoneError;
}

void CMkSocket::OnEvent(Uint32 Event)
{
    if (CMkEvent::EventRead&Event) {
        OnEventRead();
    } else if (CMkEvent::EventWrite&Event) {
        OnWrite();
    } else if (CMkEvent::EventError&Event) {
        if (TcpSession == m_SockType
            || TcpClient == m_SockType) {
            OnClose();
        }
    } else if (CMkEvent::EventRemove&Event) {
        OnEventRemoved();
    }
}

void CMkSocket::OnEventRead()
{
    char pbuf[2] = { 0 };
    int nRet = 0;
    switch (m_SockType) {
    case TcpListener:
        OnAccept();
        break;
    case TcpClient:
    case TcpSession:
        nRet = recv(m_Socket, pbuf, 2, MSG_PEEK);
        if (nRet <= 0) {
            OnClose();
        } else {
            OnRecv();
        }
        break;
    case UdpSession:
        OnRecvFrom();
        break;
    default:
        break;
    }
}

Uint32 CMkSocket::GetPeerAddr()
{
    struct sockaddr_in Remote;
    socklen_t addrlen = sizeof(struct sockaddr);
    int nRet = getpeername(m_Socket, (sockaddr*)&Remote, &addrlen);
    if (-1 == nRet) {
        MkErrorLog("get peer addr failed\n");
        return NoneError;
    }
    m_RemotePort = htons(Remote.sin_port);
    m_RemoteHost = inet_ntoa(Remote.sin_addr);
    return NoneError;
}

Uint32 CMkSocket::GetLocalAddr()
{
    struct sockaddr_in Local;
    socklen_t addrlen = sizeof(struct sockaddr);
    int nRet = getsockname(m_Socket, (sockaddr*)&Local, &addrlen);
    if (-1 == nRet) {
        MkErrorLog("get peer addr failed\n");
        return NoneError;
    }
    m_LocalPort = htons(Local.sin_port);
    m_LocalHost = inet_ntoa(Local.sin_addr);
    return NoneError;
}

CMkSocket::~CMkSocket()
{
    m_pEvent = nullptr;
    m_pTimer = nullptr;
    if (INVALID_SOCKET != m_Socket) {
        closesocket(m_Socket);
        shutdown(m_Socket, 1);
        m_Socket = INVALID_SOCKET;
    }
    m_UnSendList.Clear();
}
